package com.demo.study.thread.self;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author baymax
 * @since 2025-07-04
 */
@Data
public class SelfThreadPool {
    private final int corePoolSize;

    private final int maximumPoolSize;

    private final long keepAliveTime;

    private final TimeUnit unit;

    private final BlockingQueue<Runnable> blockQueue;
    private final RejectHandler rejectHandler;

    public SelfThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
        BlockingQueue<Runnable> blockQueue, RejectHandler rejectHandler) {
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.keepAliveTime = keepAliveTime;
        this.unit = unit;
        this.blockQueue = blockQueue;
        this.rejectHandler = rejectHandler;
    }

    private final List<Thread> coreThreads = new ArrayList<>();

    private final List<Thread> supportThreads = new ArrayList<>();

    /**
     * 启动线程
     */
    public void execute(Runnable command) {
        if (coreThreads.size() < corePoolSize) {
            Thread coreThread = new CoreWorker();
            coreThread.setName("core-t-" + coreThreads.size());
            coreThreads.add(coreThread);
            coreThread.start();
        }
        if (blockQueue.offer(command)) {
            return;
        }
        // 如果阻塞队列满了，创建一个辅助线程来执行
        if (supportThreads.size() + coreThreads.size() < maximumPoolSize) {
            Thread supportThread = new SupportWorker(command);
            supportThread.setName("support-t-" + supportThreads.size());
            supportThreads.add(supportThread);
            supportThread.start();
            return;
        }
        if (!blockQueue.offer(command)) {
            rejectHandler.reject(command, this);
        }
    }

    public void join() {
        while (!blockQueue.isEmpty()) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private class CoreWorker extends Thread {
        @Override
        public void run() {
            while (true) {
                try {
                    Runnable command = blockQueue.take();
                    command.run();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    private class SupportWorker extends Thread {
        private Runnable command;

        public SupportWorker(Runnable command) {
            this.command = command;
        }

        @Override
        public void run() {
            while (true) {
                if (command != null) {
                    command.run();
                    command = null;
                } else {
                    try {
                        Runnable command = blockQueue.poll(keepAliveTime, unit);
                        if (command == null) {
                            break;
                        }
                        command.run();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
            supportThreads.remove(Thread.currentThread());
            System.out.println("辅助线程已关闭");
        }
    }
}
